package HighConcurrency.Lock;

import java.awt.image.VolatileImage;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.Exchanger;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class LockDemo {
   static int count = 0;
   static AtomicInteger ai=new AtomicInteger(0);//原子类，可以保证线程安全

    volatile  int a;//线程安全,轻量级可见性，不保证原子性，不保证并发安全问题
    //禁止指令重排，指令重排是重新排列的执行顺序，容易导致数据不一致
    public static void main(String[] args) throws InterruptedException {
        Lock lock=new ReentrantLock();//锁
        //ReentrantLock 是可重入锁，可以重复利用的锁
        //Lock的实现类是ReentrantLock

        ReadWriteLock readwriteLock=new ReentrantReadWriteLock();//读写锁，参数为true，则表示为公平锁，为false则表示为非公平锁
        Lock lock1=readwriteLock.writeLock();//写锁，写锁只能被一个线程使用，但是可以同时被多个线程使用
        Lock lock2=readwriteLock.readLock();//读锁，读锁可以同时被多个线程使用，但是不能同时被写锁使用

        //在资源有限的情况下，线程之间的抢占和执行并不均等，这就是非公平策略
        //在公平策略的情况下，任务在执行的时候会有一个队列，线程按照队列的顺序执行，也就是先来的线程先执行，机会基本平等
        //相对而言，非公平策略效率更高

        CountDownLatch countDownLatch=new CountDownLatch(10);//闭锁/线程递减锁，对线程计数归零前阻塞,
        //当一组线程都完成之后要跑一个新的线程，用CountDownLatch

        CyclicBarrier cyclicBarrier=new CyclicBarrier(10);//栅栏，线程达到指定数量后，栅栏才会打开，栅栏打开后，线程才能继续执行
        //当所有线程都达到栅栏，栅栏才会打开，栅栏打开后，线程才能继续执行

        Exchanger<String> exchanger=new Exchanger<>();//交换机，两个线程之间交换数据，交换完成之后，两个线程继续执行

        Semaphore semaphore=new Semaphore(5);//信号量，控制线程的数量，
        // 可以控制线程的数量，但是不能控制线程的执行时间，只能控制线程的并发度
        //在执行前需要获取一个许可，否则会阻塞，获取许可成功后，线程才能继续执行
        //实际效果用于来限流



        new  Thread(new add()).run();
        new  Thread(new add()).run();
        //new Thread(new add(lock1)).start();
        //new Thread(new add(lock1)).start();
        System.out.println("count = " + ai);
        //主函数所在的类也是一个线程
        //Thread.sleep(2000);
        System.out.println("count = " + count);
    }
}
class add implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 10000; i++) {
            //LockDemo.count++;
            LockDemo.ai.incrementAndGet();//++i
            //LockDemo.ai.getAndIncrement();//i++

        }
    }
//    private Lock lock;
//    public add(Lock lock){
//        this.lock=lock;
//    }
//    @Override
//    public void run() {
//        lock.lock();//加锁
//            for (int i = 0; i < 10000; i++) {
//                LockDemo.count++;
//            }
//        lock.unlock();//解锁
//    }

//    @Override
//    public void run() {
//        synchronized (add.class){//锁住的是类对象，所有线程都锁住的是同一个对象，所以是同步的
//        for (int i = 0; i < 10000; i++) {
//            LockDemo.count++;
//        }
//    }
//    }
}